/**
 * 封装foreach
 * @param {*} source
 * @param {*} callback
 * @param {boolean} allOwnKeys 是否包含原型属性
 * @returns
 */
export const forEach = (source, callback, { allOwnKeys = false } = {}) => {
    if (source === undefined || source === null) return;
    if (typeof source !== 'object') {
        source = [source];
    }
    if (Array.isArray(source)) {
        for (let i = 0, len = source.length; i < len; i++) {
            callback.call(null, source[i], i);
        }
    } else {
        const keys = allOwnKeys
            ? Object.getOwnPropertyNames(source)
            : Object.keys(source);
        let key = null;
        for (let i = 0, len = keys.length; i < len; i++) {
            key = keys[i];
            callback.call(null, source[key], key);
        }
    }
    return source;
};

/**
 * 获取数据类型
 * @param {*} d
 * @returns
 */
export const getType = (d) => {
    return {}.toString.call(d).slice(8, -1).toLowerCase();
};

/**
 * 是否为数组
 * @param {*} d
 * @returns
 */
export const isArray = (d) => {
    return getType(d) === 'array';
};

/**
 * 是否为对象
 * @param {*} d
 * @returns
 */
export const isObject = (d) => {
    return getType(d) === 'object';
};

/**
 * 是否为函数
 * @param {*} d
 * @returns
 */
export const isFunction = (d) => {
    return getType(d) === 'function';
};

/**
 * 合并
 * @param {*} a
 * @param {*} b
 * @returns
 */
export const merge = (a, b) => {
    forEach(b, (val, key) => {
        if (isObject(a[key]) && isObject(val)) {
            a[key] = merge(a[key], val);
        } else {
            a[key] = val;
        }
    });
    return a;
};

/**
 * bind
 * @param {*} fn
 * @param {*} context
 * @returns
 */
export const bind = (fn, context) => {
    return function wrap(...args) {
        return fn.apply(context, args);
    };
};

/**
 * 扩展继承
 * @param {*} a
 * @param {*} b
 * @param {*} context
 * @returns
 */
export const extend = (a, b, context, { allOwnKeys = false } = {}) => {
    forEach(
        b,
        function (value, key) {
            if (context && isFunction(b[key])) {
                a[key] = bind(value, context);
            } else {
                a[key] = value;
            }
        },
        { allOwnKeys },
    );
    return a;
};

/**
 * 字符串转为数字
 * @param {*} str 
 * @returns 
 */
export const stringToNumber = (str) => {
    if (typeof str !== 'string') return str;
    const parseStr = Number(str);
    return isNaN(parseStr) ? str : parseStr;
}

/**
 * 判断是否为json字符串
 * @param {*} str 
 * @returns 
 */
export const isJson = (str) => {
    if (typeof str !== 'string') return false;
    try {
        let data = JSON.parse(str);
        return isObject(data);
    } catch (e) { }
    return false;
}


/**
 * json格式化
 */
export const jsonParse = (str) => {
    if (!isJson(str)) return str;
    return JSON.parse(str)
}
